<?php

namespace app\common\model;

use app\api\model\MobileCode;
use app\common\library\Broadcast;
use think\Exception;
use general\Random;
use general\Tree;
use think\facade\Request as FacadeRequest;
use think\Model;

/**
 * 会员公共模型
 * @property int    $id              会员ID
 * @property string $password        密码密文
 * @property string $salt            密码盐
 * @property int    $login_failure   登录失败次数
 * @property string $last_login_time 上次登录时间
 * @property string $last_login_ip   上次登录IP
 * @property string $email           会员邮箱
 * @property string $mobile          会员手机号
 */
class User extends Model
{

    use Broadcast;
    //查询用户信息
    public function selectUserInfo()
    {
        $userInfo = $this->select()->toArray();
        return $userInfo;
    }
    //获取当前做大的id
    public function getMaxId()
    {
        $maxId = $this->max('id');
        $maxId = $maxId ?? 0;
        return intval($maxId);
    }


    /**
     * 重置用户密码
     * @param int|string $uid         用户ID
     * @param string     $newPassword 新密码
     * @return int|User
     */
    public function resetPassword($uid, $newPassword)
    {
        $salt   = Random::build('alnum', 16);
        $passwd = encrypt_password($newPassword, $salt);
        return $this->where(['id' => $uid])->update(['password' => $passwd, 'salt' => $salt]);
    }

    //更新头像
    public function resetAvatar($uid, $newAvatarUrl)
    {
        return $this->where(['id' => $uid])->update(['avatar' => $newAvatarUrl]);
    }


    //设置支付密码
    public function payPassword($uid, $newPassword)
    {
        $passwd = password_hash($newPassword, PASSWORD_DEFAULT);
        return $this->where(['id' => $uid])->update(['pay_password' => $passwd, 'is_pay_password' => 1]);
    }

    //验证2次密码输入是否一致
    public function checkPasswordIsTrue($newPassword, $confirmPassword)
    {
        return ($newPassword === $confirmPassword) ? true : false;
    }

    //验证支付密码是否正确
    public function checkPayPassword($uPayPassword, $newPassword)
    {
        return password_verify($newPassword, $uPayPassword) ? true : false;
    }


    public function member()
    {
        return $this->hasOne(UserMemberLog::class, 'user_id');
    }

    //保存用户ip绑定
    public function userAuthCodeBindIp($user_id,$code)  {
        $ip = FacadeRequest::ip();

        $data=[
           'user_id'=>$user_id,
           'auth_code'=>$code,
           'ip'=>$ip
        ];
        $bind = UserAuthCodeBindIp::saveCodeBindIp($data);
        return $bind;
    }


    //支付
    public function payWatch($array_data)
    {
        $payData = [
            'appid' => get_sys_config('app_id'),
            'mchid' => rtrim(get_sys_config('mchid')), //服务商户号
            'description' => $array_data['desc'] ?? '我是描述', //商品描述	
            'out_trade_no' => $array_data['out_trade_no'], //平台订单号
            'notify_url' => get_sys_config('https') . '/' . get_sys_config('payNotifyUrl'), //通知地址
            'amount' => [
                'total' => intval($array_data['total']),
                'currency' => $array_data['currency']
            ],
            'payer' => [
                "openid" => $array_data['open_id'] // openid
            ],
            'attach' => $array_data['attach'] //附加数据
        ];
        $url =   get_sys_config('payUrl');

        $headers = $this->sign('POST', $url, json_encode($payData));
        $data =  $this->curl_post($url, json_encode($payData), $headers);
        $prepay_id = json_decode($data, true);

        if (!array_key_exists('prepay_id', $prepay_id)) {
            throw new Exception("支付错误");
        }
        $appId = get_sys_config('app_id');
        $timeStamp = strval(time());
        $nonceStr = Random::build('alnum', 32); //随机串
        $package = "prepay_id=" . $prepay_id['prepay_id'];
        $signType = 'RSA';
        $resultData = [
            'appId' => $appId,
            'timeStamp' => $timeStamp,
            'nonceStr' => $nonceStr,
            'package' => $package,
            'signType' => $signType,
            'paySign' => $this->paySign($appId, $timeStamp, $nonceStr, $package),
        ];
        return $resultData;
    }

    //退款--微信
    public static function wxRefund($array_data)
    {
        $payData = [
            'appid' => get_sys_config('app_id'),
            'mchid' => rtrim(get_sys_config('mchid')), //服务商户号
            'description' => $array_data['desc'] ?? '我是描述', //商品描述	
            'out_refund_no' => $array_data['out_trade_no'], //平台订单号
            'notify_url' => get_sys_config('https') . '/' . get_sys_config('refundsNotifyUrl'), //通知地址
            'amount' => [
                'refund' => intval($array_data['total'])
            ],
        ];
        $url =   'https://api.mch.weixin.qq.com/v3/ecommerce/refunds/apply';
        $headers = self::sign('POST', $url, json_encode($payData));
        $data =  self::curl_post($url, json_encode($payData), $headers);
        $resultData = json_decode($data, true);
        return $resultData;
    }


    /**
     * Undocumented function
     * 支付签名
     */
    public function paySign($appId, $timeStamp, $nonceStr, $package)
    {
        $mch_private_key = openssl_pkey_get_private(file_get_contents(get_sys_config('certPath') . get_sys_config('api_key')));
        $message =  $appId . "\n" . //appid
            $timeStamp . "\n" . //时间戳
            $nonceStr . "\n" .
            $package . "\n";
        //计算签名值
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        return $sign;
    }


    //头部签名
    public function sign($http_method = 'POST', $url = '', $body = '')
    {
        $mch_private_key = openssl_pkey_get_private(file_get_contents(get_sys_config('certPath') . get_sys_config('api_key')));

        $timestamp = time(); //时间戳
        $nonce = Random::build('alnum', 32); //随机串
        $url_parts = parse_url($url);

        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?{$url_parts['query']}" : ""));

        //构造签名串
        $message = $http_method . "\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $body . "\n"; //报文主体
        //计算签名值
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);

        //设置HTTP头
        $config = PublicStatus::wxCondfig();
        $token = sprintf(
            'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            $config['mchid'],
            $nonce,
            $timestamp,
            $config['serial_no'],
            $sign
        );
        $headers = [
            'Accept: application/json',
            'User-Agent: */*',
            'Content-Type: application/json; charset=utf-8',
            'Authorization: ' . $token,
        ];

        return $headers;
    }

    /**
     *  post curl
     */
    public function curl_post($url, $data, $headers = array())
    {

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置header头
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        // POST数据
        curl_setopt($ch, CURLOPT_POST, 1);
        // 把post的变量加上
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }

    /**
     * get curl
     */
    public function curl_get($url, $headers = array())
    {
        $info = curl_init();
        curl_setopt($info, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($info, CURLOPT_HEADER, 0);
        curl_setopt($info, CURLOPT_NOBODY, 0);
        curl_setopt($info, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($info, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($info, CURLOPT_SSL_VERIFYHOST, false);
        //设置header头
        curl_setopt($info, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($info, CURLOPT_URL, $url);
        $output = curl_exec($info);
        curl_close($info);
        return $output;
    }


    //判断是否是会员
    public static function isMember($uid): bool
    {
        $user = self::find($uid);
        if (!$user) {
            throw new Exception("用户没找到");
        }
        return $user->user_type !== 0 ? true : false;
    }


    //随机生成验证码
    public function sendMobile($uid, $mobile, $status)
    {
        $code = Random::build('numeric', 6);
        $res = MobileCode::saveCode(['user_id' => $uid, 'mobile' => $mobile, 'code' => $code, 'status' => $status]);
        return $res;
    }


    //检查手机验证码
    public function checkCode($uid, $mobile, $code)
    {
        $res = MobileCode::checkCode($uid, $mobile, $code);
        return $res;
    }


    //根据推广码查找用户信息
    public static function getPromotionCodeByUser($code)
    {
        $res = self::where(['promotion_code' => $code])->find();
        if (!$res) {
            throw new Exception("用户没找到");
        }
        return $res;
    }

    //根据用户id 获取
    public static function getUserById($uid)
    {
        $res = self::find($uid);
        if (!$res) {
            throw new Exception("用户没找到");
        }
        return $res;
    }

    //用户树 往下找
    public static function getUserTree($id, $pidname, $is_flag)
    {

        $user = self::where(['status' => PublicStatus::USER_STATUS_ONE])->select()->toArray();
        $tree = Tree::instance()->init($user, $pidname);
        $result = $tree->getChildrenAll($id, $is_flag);
        return $result;
    }

    //用户树 网上找
    public static function getUserTopTree($id, $pidname, $is_flag)
    {

        $user = self::where(['status' => PublicStatus::USER_STATUS_ONE])->select()->toArray();
        $tree = Tree::instance()->init($user, $pidname);
        $result = $tree->getParents($id, $is_flag);
        return $result;
    }

    //获取所有父级ID
    public static function getUserAllID($id)
    {
        $user = self::where(['status' => PublicStatus::USER_STATUS_ONE])->select()->toArray();
        $tree = Tree::instance()->init($user, 'promoter_id');
        $res = $tree->getParentsIds($id, false);
        if (count($res) > PublicStatus::ARRAY_COUNT) {
            $superior_ids = implode(',', $res);
        } else {
            $superior_ids = "";
        }
        return $superior_ids;
    }


    //入库后 生成推广二维码
    public static function onAfterInsert($model)
    {
        // //检查是否存在推广码
        // if (array_key_exists('code', $model->toArray())) {
        //     $res = self::getPromotionCodeByUser($model['code']);
        //     $promoter_id = $res->id; //推广者id
        //     $association_time = date('Y-m-d H:i:s', time()); //关联时间
        // } else {
        //     $promoter_id = 0;
        //     $association_time = NULL;
        // }
        // // $writer = new PngWriter();
        // // $url = Config::get('general.promotion_code') . $model['promotion_code'];
        // // $qrCode = QrCode::create($url)->setEncoding(new Encoding('UTF-8'))
        // //     ->setErrorCorrectionLevel(new ErrorCorrectionLevelLow())
        // //     ->setSize(260) //大小
        // //     ->setMargin(1) //边距
        // //     ->setRoundBlockSizeMode(new RoundBlockSizeModeMargin())
        // //     ->setForegroundColor(new Color(0, 0, 0))
        // //     ->setBackgroundColor(new Color(255, 255, 255));
        // // $label = Label::create('推广码') //二维码下面的文字
        // //     ->setTextColor(new Color(0, 0, 0));
        // // $result = $writer->write($qrCode);
        // // $result->getString();
        // // $qrcode = $model['id'] . '_' . $model['promotion_code'] . '.png'; //二维码文件名称
        // // $result->saveToFile(public_path() . '/storage/qrcode/' . $qrcode);
        // // $dataUri = $result->getDataUri(); //base64
        // // $code_url = full_url('/storage/qrcode/' . $qrcode);
        // // self::update(['id' => $model['id'], 'promoter_id' => $promoter_id, 'association_time' => $association_time]);

        // self::update(['id' => $model['id'], 'promoter_id' => $promoter_id, 'association_time' => $association_time]);
        // //查找上级
        // $superior_ids = self::getUserAllID($model['id']);
        // return self::update(['id' => $model['id'], 'superior_ids' => $superior_ids]);
    }



    //获取手机号
    public static function getWeChatPhone($wx_code)
    {
        $app_id = get_sys_config('app_id');
        $secret = get_sys_config('secret');
        $URL = "https://api.weixin.qq.com/sns/jscode2session?appid=$app_id&secret=$secret&js_code=$wx_code&grant_type=authorization_code";
        $apiData = file_get_contents($URL);
        $arr_data = json_decode($apiData, true);
        if (empty($arr_data)) {
            throw new Exception("获取失败,微信内部异常");
        }
        if (!array_key_exists('openid', $arr_data)) {
            throw new Exception("获取失败-errcode");
        }
        return $arr_data['openid'];
    }

    //检查手机号是否存在
    public function checkMobile($mobile)
    {
        $flag = self::where('mobile', $mobile)->find();
        return $flag ? true : false;
    }


    //检查手机号是否存在
    public static function checkOpenId($openid)
    {
        $flag = self::where('open_id', $openid)->find();

        return $flag;
    }

    /**
     * 充值 记录
     * @throws Throwable
     */
    public function getOnPayInsert($uid, $money, $memo)
    {

        $user = $this->where('id', $uid)->find();
        if ($user->brokerage_money < $money) {
            throw new Exception("佣金不足,无法转出");
        }
        if (!$user) {
            throw new Exception("用户没找到");
        }
        $before = $user->money;

        $user->money += $money;
        $user->brokerage_money -= $money;
        $user->save();

        $after = $user->money;

        $data = [
            'user_id' => $uid,
            'before' => $before,
            'money' => $money,
            'after' => $after,
            'memo' => $memo,
            'type' => PublicStatus::PUBLIC_STATUS_ONE,
        ];
        $id = UserMoneyLog::create($data)->id;

        return $id > 0 ? true : false;
    }

    //修改用户信息
    public function updateUserInfo($uid, $data)
    {
        switch ($data['type']) {
            case 'username':
                $result = $this->where(['id' => $uid])->update(['username' => $data['username'],'nickname' => $data['username']]);
                break;
            default:
                $result = "";
                break;
        }
        return $result;
    }
}
